home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
121_01
/
ml2.c
< prev
next >
Wrap
Text File
|
1985-08-19
|
21KB
|
807 lines
/*
HEADER: CUG 121.??;
TITLE: ml2 - modified l2 linker;
VERSION: 1.0;
DATE: 01/11/86;
DESCRIPTION: "ML2 is a version of Scott Layson's L2 linker which has been
modified to produce MP/M modules. The only usage change is
the addition of the -r flag which will start the specified
runtime file at the specified address, then build the rest of
the module after it.
For further information on L2, see the reference below.";
KEYWORDS: link;
SYSTEM: MP/M;
FILENAME: ML2.C;
WARNINGS: "Requires chario.c for link (this is supplied with the
distributed version of l2).
This program has not been tested by the librarian, due to
lack of the MP/M operating system.";
AUTHORS: Scott W. Layson, Stephen M. Kenton;
COMPILERS: BDS-C 1.50;
REFERENCES:
AUTHORS: Scott W. Layson;
TITLE: "The Mark of the Unicorn Linker for BDS C";
ENDREF
*/
/* ML2.C New linker for BDS C to produce MP/M modules
Written 1980 by Scott W. Layson
Modified from L2.C by Stephen M. Kenton
This code is in the public domain.
This is an improved linker for BDS C CRL format. It eliminates the
jump table at the beginning of each function in the object code,
thus saving up to 10% or so in code space with a slight improvement
in speed.
[81.4.13] Switches automatically to two-pass, windowing link
if it runs out of memory.
[81.4.13] Symbol table is now in the order that the
functions occur in memory; this seems more
useful. Also, link stats are added on the end;
this only slightly confuses SID.
[81.4.27] "-wa" appends link stats to the .sym file; "-ws"
writes them to a separate file; "-w" does
neither. "Version 2.1" message.
[81.4.27] Overlay capability now exists. It works a bit
differently from CLINK: the option
-ovl <base name> <origin>
causes symbols to be read from <base name>.sym
and produces a segment linked at <origin>. It
also defaults the name of the overlay function to
that of the first .crl file (to override, put -m
after the -ovl), and replaces c.ccc with a jump
to that function. Also note that the base
symbols are loaded at the very beginning, so name
conflicts are always resolved in favor of the
base.
[82.1.1] "-R" added to relocate the run time library.
The syntax is similar to the "-ovl" option,
but the file name is the run time library.
*/
/**************** Globals ****************/
#define OVERLAYS
#include <bdscio.h> /* for i/o buffer defs */
#define NUL 0
#define FLAG char
#define repeat while (1)
#define STDOUT 1
/* Phase control */
#define INMEM 1 /* while everything still fits */
#define DISK1 2 /* overflow; finish building table */
#define DISK2 3 /* use table to do window link */
int phase;
/* function table */
struct funct {
char fname[9];
FLAG flinkedp; /* in memory already? */
char *faddr; /* address of first ref link if not linked */
} ftab [300];
int nfuncts; /* no. of functions in table */
#define LINKED 1 /* (flinkedp) function really here */
#define EXTERNAL 2 /* function defined in separate symbol table */
char fdir [512]; /* CRL file function directory */
/* command line parameters etc. */
int nprogs, nlibs;
char progfiles [30] [15]; /* program file names */
char libfiles [20] [15]; /* library file names */
FLAG symsp, /* write symbols to .sym file? */
appstatsp, /* append stats to .sym file? */
sepstatsp; /* write stats to .lnk file? */
char mainfunct[10];
#ifdef OVERLAYS
FLAG ovlp, /* make overlay? */
relocp; /* or relocate root? */
#endif
char runfile [15]; /* run time library file name */
char symsfile [15]; /* file to load symbols from (for overlays) */
/* useful things to have defined */
struct inst {
char opcode;
char *address;
};
union ptr {
unsigned u; /* an int */
unsigned *w; /* a word ptr */
char *b; /* a byte ptr */
struct inst *i; /* an instruction ptr */
};
/* Link control variables */
union ptr codend; /* last used byte of code buffer + 1 */
union ptr exts; /* start of externals */
union ptr acodend; /* actual code-end address */
unsigned extspc; /* size of externals */
unsigned origin; /* origin of code */
unsigned buforg; /* origin of code buffer */
unsigned jtsaved; /* bytes of jump table saved */
char *lspace; /* space to link in */
char *lspcend; /* end of link area */
char *lodstart; /* beginning of current file */
/* i/o buffer */
struct iobuf {
int fd;
int isect; /* currently buffered sector */
int nextc; /* index of next char in buffer */
char buff [128];
} ibuf, obuf;
/* BDS C i/o buffer */
char symbuf[BUFSIZ];
/* seek opcodes */
#define ABSOLUTE 0
#define RELATIVE 1
#define INPUT 0
#define TRUE (-1)
#define FALSE 0
#define NULL 0
/* 8080 instructions */
#define LHLD 0x2A
#define LXIH 0x21
#define SPHL 0xF9
#define JMP 0xC3
#define CALL 0xCD
/* strcmp7 locals, made global for speed */
char _c1, _c2, _end1, _end2;
/**************** End of Globals ****************/
main (argc, argv)
int argc;
char **argv;
{
puts ("Mark of the Unicorn Linker for BDS C, vsn. 2.1M\n");
setup (argc, argv);
linkprog();
linklibs();
if (phase == DISK1) rescan();
else wrtcom();
if (symsp) wrtsyms();
}
setup (argc, argv) /* initialize function table, etc. */
int argc;
char **argv;
{
symsp = appstatsp = sepstatsp = FALSE;
ovlp = relocp = FALSE;
nprogs = 0;
nlibs = 0;
strcpy (&mainfunct, "MAIN");
strcpy (&runfile, "C.CCC");
origin = 0x100;
cmdline (argc, argv);
lspace = endext();
lspcend = topofmem() - 1024;
loadccc();
nfuncts = 0;
#ifdef OVERLAYS
if (ovlp) loadsyms();
#endif
intern (&mainfunct);
phase = INMEM;
buforg = origin;
jtsaved = 0;
}
cmdline (argc, argv) /* process command line */
int argc;
char **argv;
{
int i, progp;
if (argc < 1) {
puts ("Usage is:\n");
puts (" ml2 {program files} -l {library files} [-w]\n");
exit (1);
}
progp = TRUE;
for (i=1; i < argc; ++i) {
if (argv[i][0] == '-') {
if (!strcmp (argv[i], "-L")) progp = FALSE;
else if (!strcmp (argv[i], "-W")) symsp = TRUE;
else if (!strcmp (argv[i], "-WA")) symsp = appstatsp = TRUE;
else if (!strcmp (argv[i], "-WS")) symsp = sepstatsp = TRUE;
else if (!strcmp (argv[i], "-M")) {
if (++i >= argc) Fatal ("-m argument missing.\n");
strcpy (&mainfunct, argv[++i]);
}
#ifdef OVERLAYS
else if (!strcmp (argv[i], "-OVL")) {
ovlp = TRUE;
if (i + 2 >= argc) Fatal ("-ovl argument missing.\n");
strcpy (&symsfile, argv[++i]);
sscanf (argv[++i], "%x", &origin);
}
else if (!strcmp (argv[i], "-R")) {
relocp = TRUE;
if (i + 2 >= argc) Fatal ("-r argument missing");
strcpy (&runfile, argv[++i]);
sscanf (argv[++i], "%x", &origin);
}
#endif
else printf ("Unknown option: '%s'\n", argv[i]);
}
else {
if (progp) strcpy (&progfiles[nprogs++], argv[i]);
else strcpy (&libfiles[nlibs++], argv[i]);
}
}
if (ovlp) strcpy (&mainfunct, &progfiles[0]);
strcpy(&libfiles[nlibs++], "LOCAL.CRL") ;
strcpy(&libfiles[nlibs++], "DEFF.CRL") ;
strcpy(&libfiles[nlibs++], "DEFF2.CLR") ;
}
loadccc() /* load C.CCC (runtime library) */
{
union ptr temp;
unsigned len;
codend.b = lspace;
if (!ovlp) {
if (copen (&ibuf, runfile) < 0)
Fatal ("Can't open C.CCC\n");
if (cread (&ibuf, lspace, 128) < 128) /* read a sector */
Fatal ("C.CCC: read error!\n");
temp.b = lspace + 0x17;
len = *temp.w; /* how long is it? */
cread (&ibuf, lspace + 128, len - 128); /* read rest */
codend.b += len;
cclose (&ibuf);
}
else